package com.xiaomengkuan.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaomengkuan.common.entity.vo.PageVo;
import com.xiaomengkuan.common.exception.CasualException;
import com.xiaomengkuan.common.exception.RequestBodyArgumentException;
import com.xiaomengkuan.common.util.DetailSelector;
import com.xiaomengkuan.common.util.R;
import com.xiaomengkuan.product.entity.pojo.*;
import com.xiaomengkuan.product.entity.vo.AdminProductDetailVo;
import com.xiaomengkuan.product.entity.vo.ProductDetailResponseVo;
import com.xiaomengkuan.product.entity.vo.ProductResponseVo;
import com.xiaomengkuan.product.mapper.*;
import com.xiaomengkuan.product.service.ProductService;
import com.xiaomengkuan.product.util.RelationSelector;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.xiaomengkuan.common.util.YsjUtil.*;

/**
 * @author Faraj Mujey
 * -- Creation Time: 2021-01-26 7:04 下午, File Encoding: utf8 --
 */
@Service
public class ProductServiceImpl implements ProductService {
    @Resource
    private ProductMapper productMapper;
    @Resource
    private UserProductRelationMapper userProductRelationMapper;
    @Resource
    private ProductTagRelationMapper productTagRelationMapper;
    @Resource
    private TagMapper tagMapper;
    @Resource
    private PictureMapper pictureMapper;
    @Resource
    private StoryMapper storyMapper;

    /**
     * 查询商品详细
     *
     * @param requestBody requestBody
     * @return R
     */
    @Override
    public ProductDetailResponseVo getDetailById(Map<String, Object> requestBody) {
        String id = (String) requestBody.get("id");
        String userId = (String) requestBody.get("userId");
        if (stringsCompliant(id)) {
            Product product = productMapper.selectById(id);
            if (product != null) {
                ProductDetailResponseVo productDetailResponseVo = new ProductDetailResponseVo();
                BeanUtils.copyProperties(product, productDetailResponseVo);
                if (stringsCompliant(userId)) {
                    Map<String, Object> condition = new HashMap<>();
                    condition.put("user_id", userId);
                    condition.put("product_id", id);
                    condition.put("deleted", 0);
                    List<UserProductRelation> userProductRelations = userProductRelationMapper.selectList(new QueryWrapper<UserProductRelation>().allEq(condition));
                    if (userProductRelations.size() > 0) {
                        userProductRelations.forEach(relation -> {
                            if (relation.getRelation() == RelationSelector.LIKE) {
                                productDetailResponseVo.setLiked(true);
                            } else if (relation.getRelation() == RelationSelector.FAVOURITE) {
                                productDetailResponseVo.setFavourited(true);
                            }
                        });
                    }
                }
                List<Story> stories = storyMapper.selectList(new QueryWrapper<Story>().eq(
                        "product_id", id));
                productDetailResponseVo.setStories(stories);
                List<ProductTagRelation> relations =
                        productTagRelationMapper.selectList(new QueryWrapper<ProductTagRelation>().eq("product_id", id));
                List<String> tagIds = relations.stream().map(ProductTagRelation::getTagId).collect(Collectors.toList());
                if (tagIds.size() > 0) {
                    List<Tag> tags = tagMapper.selectBatchIds(tagIds);
                    if (tags.size() > 0) {
                        productDetailResponseVo.setTags(tags);
                    }
                }
                List<Picture> pictures =
                        pictureMapper.selectList(new QueryWrapper<Picture>().eq(
                                "product_id", id));
                productDetailResponseVo.setProductDetailPictures(new ArrayList<>());
                productDetailResponseVo.setProductMainPictures(new ArrayList<>());
                if (pictures.size() > 0) {
                    for (int i = 0; i < pictures.size(); i++) {
                        if (i < 9) {
                            Picture picture = pictures.get(i);
                            if (picture.getType() == 0) {
                                productDetailResponseVo.getProductMainPictures().add(picture);
                            } else if (picture.getType() == 1) {
                                productDetailResponseVo.getProductDetailPictures().add(picture);
                            }
                        }
                        long count = pictures.stream().filter(picture -> picture.getType() == 1).count();
                        if (count > 8) productDetailResponseVo.setHasMore(true);
                    }
                }
                return productDetailResponseVo;
            } else {
                return null;
            }
        } else {
            throw new RequestBodyArgumentException();
        }
    }

    /**
     * 根据标签id查找商品列表
     *
     * @param id   标签id
     * @param page
     * @return R
     */
    @Override
    public List<ProductResponseVo> getListByTag(String id, int page) {
        // TODO: 根据标签id查找商品列表 < 2021-01-27, farajmujey > 📣
        return null;
    }

    @Override
    public boolean isExist(String id) {
        Product product = productMapper.selectById(id);
        return product != null;
    }

    /**
     * 分页查询首页数据
     *
     * @param requestBody requestBody
     * @return PageVo
     */
    @Override
    public PageVo<ProductResponseVo> getIndex(Map<String, Object> requestBody) {
        String userId = (String) requestBody.get("userId");
        Integer current = (Integer) requestBody.get("current");
        Integer size = (Integer) requestBody.get("size");
        boolean b = objsCompliant(userId, current, size);
        if (b) {
            Page<Product> productPage = new Page<>(current, size);
            QueryWrapper<Product> wrapper = new QueryWrapper<>();
            // TODO: 查询用户喜欢的商品所在的标签并构造查询条件 < 2021-02-15, farajmujey > 📣
            Page<Product> page = productMapper.selectPage(productPage, wrapper);
            List<ProductResponseVo> collect = page.getRecords().stream().map(e -> {
                String productId = e.getId();
                ProductResponseVo productResponseVo = new ProductResponseVo();
                BeanUtils.copyProperties(e, productResponseVo);
                if (!userId.equals("0")) {
                    Map<String, Object> allEqConditions = new HashMap<>();
                    allEqConditions.put("product_id", productId);
                    allEqConditions.put("user_id", userId);
                    allEqConditions.put("deleted", 0);
                    List<UserProductRelation> userProductRelations =
                            userProductRelationMapper.selectList(new QueryWrapper<UserProductRelation>()
                                    .allEq(allEqConditions));
                    if (userProductRelations.size() > 0) {
                        userProductRelations.forEach(relation -> {
                            if (relation.getRelation() == RelationSelector.LIKE) {
                                productResponseVo.setLiked(true);
                            } else if (relation.getRelation() == RelationSelector.FAVOURITE) {
                                productResponseVo.setFavourited(true);
                            }
                        });
                    }
                }
                List<ProductTagRelation> productTagRelations =
                        productTagRelationMapper.selectList(new QueryWrapper<ProductTagRelation>().eq("product_id", productId));
                List<String> tagIds = productTagRelations.stream().map(ProductTagRelation::getTagId).collect(Collectors.toList());
                if (tagIds.size() > 0) {
                    List<Tag> tags = tagMapper.selectBatchIds(tagIds);
                    productResponseVo.setTags(tags);
                }
                return productResponseVo;
            }).collect(Collectors.toList());
            return pageFilling(page.getCurrent(), page.getSize(), page.getTotal()
                    , collect);
        } else {
            throw new RequestBodyArgumentException();
        }

    }

    @Override
    public PageVo<ProductResponseVo> getAll_Admin(Map<String, Object> requestBody) {
        Integer current = (Integer) requestBody.get("current");
        IPage<Product> page = new Page<>(current, 10);
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        String key = (String) requestBody.get("key");
        if (stringsCompliant(key)) {
            wrapper.eq("id", key).or().like("title", key);
        }
        String order = (String) requestBody.get("order");
        Boolean isAsc = (Boolean) requestBody.get("isAsc");
        if (stringsCompliant(order)) {
            wrapper.orderBy(true, isAsc, order);
        }
        IPage<Product> productIPage = productMapper.selectPage(page, wrapper);
        List<ProductResponseVo> collect = productIPage.getRecords().stream().map(p -> {
            ProductResponseVo productResponseVo = new ProductResponseVo();
            BeanUtils.copyProperties(p, productResponseVo);
            String id = p.getId();
            List<ProductTagRelation> product_id =
                    productTagRelationMapper.selectList(new QueryWrapper<ProductTagRelation>().eq(
                            "product_id", id));
            if (product_id.size() > 0) {
                List<Tag> tags = new ArrayList<>();
                for (ProductTagRelation productTagRelation : product_id) {
                    Tag tag = tagMapper.selectById(productTagRelation.getTagId());
                    if (tag != null)
                        tags.add(tag);
                }
                productResponseVo.setTags(tags);
            }
            return productResponseVo;
        }).collect(Collectors.toList());
        return pageFilling(productIPage.getCurrent(), productIPage.getSize(),
                productIPage.getTotal(), collect);
    }

    @Override
    @Transactional
    public R insert(Map<String, Object> requestBody) {
        String title = (String) requestBody.get("title");
        String img = (String) requestBody.get("img");
        if (stringsCompliant(title, img)) {
            Product product = new Product();
            // 设置一些属性
            product.setImg(img);
            product.setTitle(title);
            product.setFavourite(0);
            product.setLike(0);
            String price = (String) requestBody.get("price");
            if (objsCompliant(price)) {
                product.setPrice(new BigDecimal(price));
            }
            Integer sort = (Integer) requestBody.get("sort");
            if (objsCompliant(sort)) {
                product.setSort(sort);
            }
            String summary = (String) requestBody.get("summary");
            if (stringsCompliant(summary)) {
                product.setSummary(summary);
            }
            int productInsertSuccess = productMapper.insert(product);
            if (productInsertSuccess > 0) {
                String productId = product.getId();
                // 添加tag和product的关系
                List<String> tags = (List<String>) requestBody.get("tags");
                if (tags != null && tags.size() > 0) {
                    for (String tag : tags) {
                        ProductTagRelation productTagRelation = new ProductTagRelation();
                        productTagRelation.setProductId(productId);
                        productTagRelation.setTagId(tag);
                        int insert = productTagRelationMapper.insert(productTagRelation);
                        if (insert < 0) {
                            throw new CasualException(5000,
                                    DetailSelector.INSERT_ERROR);
                        }
                    }
                }
                // 保存图片
                List<LinkedHashMap<String, Object>> pic =
                        (List<LinkedHashMap<String, Object>>) requestBody.get(
                                "pic");
                if (pic != null && pic.size() > 0) {
                    for (LinkedHashMap<String, Object> map : pic) {
                        Picture picture = new Picture();
                        picture.setType((Integer) map.get("type"));
                        picture.setUrl((String) map.get("url"));
                        int insert = pictureMapper.insert(picture);
                        if (insert < 0) {
                            throw new CasualException(5000,
                                    DetailSelector.INSERT_ERROR);
                        }
                    }
                }
                // 保存故事
                List<LinkedHashMap<String, Object>> stories = (List<LinkedHashMap<String, Object>>) requestBody.get("stories");
                if (stories != null && stories.size() > 0) {
                    for (Map<String, Object> m : stories) {
                        Story story = new Story();
                        story.setContext((String) m.get("context"));
                        story.setTitle((String) m.get("title"));
                        story.setProductId(productId);
                        int insert = storyMapper.insert(story);
                        if (insert < 0) {
                            throw new CasualException(5000,
                                    DetailSelector.INSERT_ERROR);
                        }
                    }
                }
            }
            return R.ok().detail(DetailSelector.INSERT_SUCCESS);
        } else {
            throw new RequestBodyArgumentException();
        }
    }

    @Override
    public List<Story> getStories(String productId, Map<String, Object> requestBody) {
        QueryWrapper<Story> wrapper = new QueryWrapper<>();
        wrapper.eq("product_id", productId);
        if (requestBody != null) {
            String key = (String) requestBody.get("key");
            if (stringsCompliant(key)) {
                wrapper.eq("id", key).or().like("title", key);
            }
        }
        return storyMapper.selectList(wrapper);
    }

    @Override
    public R getStory(String id) {
        if (stringsCompliant(id)) {
            Story story = storyMapper.selectById(id);
            if (story != null) {
                return R.ok().detail(DetailSelector.QUERY_SUCCESS).putItem(story);
            } else {
                throw new CasualException(5000, DetailSelector.QUERY_ERROR);
            }
        } else {
            throw new CasualException(5000, DetailSelector.QUERY_ERROR);
        }
    }

    @Override
    public R saveStory(Map<String, Object> requestBody) {
        String id = (String) requestBody.get("id");
        if (stringsCompliant(id)) {
            Story storyObj = new Story();
            storyObj.setId(id);
            String context = (String) requestBody.get("context");
            if (stringsCompliant(context)) {
                storyObj.setContext(context);
            }
            String title = (String) requestBody.get("title");
            if (stringsCompliant(title)) {
                storyObj.setTitle(title);
            }
            if (stringsCompliant(storyObj.getContext()) || stringsCompliant(storyObj.getTitle())) {
                int i = storyMapper.updateById(storyObj);
                if (i > 0) return R.ok().detail(DetailSelector.UPDATE_SUCCESS);
                else return R.err().detail(DetailSelector.UPDATE_ERROR);
            } else {
                return R.err().detail("没有改变，无需更改");
            }
        } else {
            throw new RequestBodyArgumentException();
        }
    }

    @Override
    public R createStory(Map<String, Object> requestBody) {
        String title = (String) requestBody.get("title");
        String context = (String) requestBody.get("context");
        String productId = (String) requestBody.get("productId");
        if (stringsCompliant(title, context, productId)) {
            Story story = new Story();
            story.setTitle(title);
            story.setContext(context);
            story.setProductId(productId);
            int insert = storyMapper.insert(story);
            if (insert > 0) {
                return R.ok().detail(DetailSelector.INSERT_SUCCESS);
            } else {
                return R.err().detail(DetailSelector.INSERT_ERROR);
            }
        } else {
            throw new RequestBodyArgumentException();
        }
    }

    @Override
    public R deleteStory(String id) {
        if (stringsCompliant(id)) {
            int i = storyMapper.deleteById(id);
            if (i > 0) {
                return R.ok().detail(DetailSelector.DELETE_SUCCESS);
            } else {
                return R.err().detail(DetailSelector.DELETE_ERROR);
            }
        } else {
            throw new CasualException(5000, "参数错误");
        }
    }

    @Override
    public R pictures(String id) {
        if (stringsCompliant(id)) {
            List<Picture> mainPics = new ArrayList<>();
            List<Picture> detailPics = new ArrayList<>();
            List<Picture> pics =
                    pictureMapper.selectList(new QueryWrapper<Picture>().eq(
                            "product_id", id));
            if (pics.size() > 0) {
                pics.forEach(entity -> {
                    if (entity.getType() == 0) {
                        mainPics.add(entity);
                    } else {
                        detailPics.add(entity);
                    }
                });
                return R.ok().detail(DetailSelector.QUERY_SUCCESS).put(
                        "mainPics", mainPics).put("detailPics", detailPics);
            } else {
                return R.err().detail(DetailSelector.QUERY_EMPTY);
            }
        } else {
            throw new CasualException(5000, "参数错误");
        }
    }

    @Override
    public R savePicture(Map<String, Object> requestBody) {
        String productId = (String) requestBody.get("productId");
        String url = (String) requestBody.get("url");
        Integer type = (Integer) requestBody.get("type");
        if (objsCompliant(productId, url, type)) {
            Picture picture = new Picture();
            picture.setType(type);
            picture.setUrl(url);
            picture.setProductId(productId);
            int insert = pictureMapper.insert(picture);
            return insert > 0 ? R.ok().detail(DetailSelector.INSERT_SUCCESS)
                    : R.err().detail(DetailSelector.INSERT_ERROR);
        } else {
            throw new RequestBodyArgumentException();
        }
    }

    @Override
    public R deletePicture(String id) {
        int i = pictureMapper.deleteById(id);
        return i > 0 ? R.ok().detail(DetailSelector.DELETE_SUCCESS) :
                R.err().detail(DetailSelector.DELETE_ERROR);
    }

    @Override
    public R getInfo(String id) {
        Product product = productMapper.selectById(id);
        AdminProductDetailVo adminProductDetailVo = new AdminProductDetailVo();
        BeanUtils.copyProperties(product, adminProductDetailVo);
        // 将tags填充之vo中
        List<String> tagIds = productTagRelationMapper.selectList(new QueryWrapper<ProductTagRelation>().eq("product_id", id))
                .stream().map(ProductTagRelation::getTagId).collect(Collectors.toList());
        if (tagIds.size() > 0) {
            List<String> tags =
                    tagMapper.selectBatchIds(tagIds).stream().map(Tag::getId).collect(Collectors.toList());
            adminProductDetailVo.setTags(tags);
        }
        return R.ok().detail(DetailSelector.QUERY_SUCCESS).putItem(adminProductDetailVo);
    }

    @Override
    @Transactional
    public R saveInfo(Map<String, Object> requestBody) {
        String id = (String) requestBody.get("id");
        if (stringsCompliant(id)) {
            Product product = new Product();
            product.setId(id);
            String title = (String) requestBody.get("title");
            if (stringsCompliant(title)) {
                product.setTitle(title);
            }
            String img = (String) requestBody.get("img");
            if (stringsCompliant(img)) {
                product.setImg(img);
            }
            int like = (int) requestBody.get("like");
            if (objsCompliant(like)) {
                product.setLike(like);
            }
            int favourite = (int) requestBody.get("favourite");
            if (objsCompliant(favourite)) {
                product.setFavourite(favourite);
            }
            String price = (String) requestBody.get("price");
            if (stringsCompliant(price)) {
                product.setPrice(new BigDecimal(price));
            }
            String summary = (String) requestBody.get("summary");
            if (stringsCompliant(summary)) {
                product.setSummary(summary);
            }
            int i = productMapper.updateById(product);
            if (i > 0) {
                List<String> newTags = (List<String>) requestBody.get("newTags");
                List<String> tags = (List<String>) requestBody.get("tags");
                if (tags.size() <= 0) {
                    if (newTags.size() > 0) {
                        List<ProductTagRelation> ptrs = newTags.stream().map(entity -> {
                            ProductTagRelation productTagRelation =
                                    new ProductTagRelation();
                            productTagRelation.setProductId(id);
                            productTagRelation.setTagId(entity);
                            return productTagRelation;
                        }).collect(Collectors.toList());
                        ptrs.forEach(productTagRelationMapper::insert);
                    }
                } else {
                    for (String newTag : newTags) {
                        if (!tags.contains(newTag)) {
                            ProductTagRelation productTagRelation =
                                    new ProductTagRelation();
                            productTagRelation.setProductId(id);
                            productTagRelation.setTagId(newTag);
                            productTagRelationMapper.insert(productTagRelation);
                        }
                    }
                    for (String tag : tags) {
                        if (!newTags.contains(tag)) {
                            Map<String, String> condition = new HashMap<>();
                            condition.put("product_id", id);
                            condition.put("tag_id", tag);
                            productTagRelationMapper.delete(new QueryWrapper<ProductTagRelation>().allEq(condition));
                        }
                    }
                }
                return R.ok().detail(DetailSelector.UPDATE_SUCCESS);
            } else {
                return R.err().detail(DetailSelector.UPDATE_ERROR);
            }
        } else {
            throw new RequestBodyArgumentException();
        }
    }

    @Override
    @Transactional
    public R removeProduct(String id) {
        // 删除商品本身
        productMapper.deleteById(id);
        // 删除标签关联关系
        productTagRelationMapper.delete(new QueryWrapper<ProductTagRelation>().eq("product_id", id));
        // 删除故事
        storyMapper.delete(new QueryWrapper<Story>().eq("product_id", id));
        // 删除图片
        pictureMapper.delete(new QueryWrapper<Picture>().eq("product_id", id));
        //删除用户记录
        userProductRelationMapper.delete(new QueryWrapper<UserProductRelation>().eq("product_id", id));
        return R.ok().detail(DetailSelector.DELETE_SUCCESS);
    }
}
